/****************************************************************************
 * user manage
 * Owner : apleilx
 * func:
 * 系统拥有一个根用户，拥有完全控制权限
 * 普通用户三种：1.管理员  2.操作员
 * 超级管理员可管理所有其他的非超级用户
 * 普通管理员只可以管理其下属的用户
 * 操作员只可以进行操作，无管理权限
 * **************************************************************************/
#define _USER_MANAGE_MODULE_
#include "usermanage.h"
#include "dataproc.h"
#include "str_ext.h"

void user_copy(user_type *user_src, user_type *user_des);
void user_str_copy(const void* src, void *des, int16_t len_max);

/****************************************************************************
 * user info init
 * **************************************************************************/
void user_manage_init(void)
{
    uint32_t Cnt;
    /*slave st check*/
    for (Cnt = 1; Cnt < USER_MAX; Cnt++)
    {
        if (user.user_list[Cnt].id_owner >= USER_MAX)
        {
            user.user_list[Cnt].id_owner = 0;
        }
        if (user.user_list[Cnt].right == 0xFFFFFFFF)
        {
            user.user_list[Cnt].right = 0;
        }
    }
    
	if((user.user_list[0].name[0] == 0) || (user.user_list[0].name[0] == 0xFF))
	{
		user_str_copy("admin", user.user_list[0].name, USER_NAME_LEN);
	}
	
    user.user_right_mask = USER_RIGHT_OPERATOR_MSK;
    user.user_list[0].right = USER_RIGHT_MANAGEER_MSK | USER_RIGHT_OPERATOR_MSK;
    user.user_list[0].b_enabled = 1;
	
    /*sel id 0*/
    user_id_sel(0);    
    
    user_enable_list_get();
}

/****************************************************************************
 * user login st set
 * **************************************************************************/
user_err_type user_login_st_set(uint8_t St)
{
    user.st_login = St;
    
    return USER_OK;
}

/****************************************************************************
 * user str copy
 * **************************************************************************/
void user_str_copy(const void* src, void *des, int16_t len_max)
{
	uint8_t const *ps;
	uint8_t *pd;
	
	ps = src;
	pd = des;
	
	len_max--;
	
	while(len_max--)
	{
		if(*ps==0)
		{
			break;
		}
		*pd++ = *ps++;
	}
	
	*pd = 0;
}

/****************************************************************************
 * user right mask set
 * **************************************************************************/
user_err_type user_right_mask_set(uint32_t msk)
{
    if(0 != (msk & (~USER_RIGHT_OPERATOR_MSK)))
    {
        return USER_ERR_RIGHT;
    }
    
    user.user_right_mask = msk;
	
    user.user_list[0].right = USER_RIGHT_MANAGEER_MSK | msk;
    
    if(user.id_now == 0)
    {
        user.user_now.right = user.user_list[0].right;
    }
    
    return USER_OK;
}

/****************************************************************************
 * user selected
 * **************************************************************************/
user_err_type user_id_sel(uint8_t id)
{
    if (id >= USER_MAX)
    {
        return USER_ERR_ID;
    }

    if(!user.user_list[id].b_enabled)
        return USER_ERR_ID;
    
    user.st_login = USER_LOGIN_NONE;
    user.id_now = id;
    user_copy(&user.user_list[id], &user.user_now);

    return USER_OK;
}

/****************************************************************************
 * user selected
 * **************************************************************************/
user_err_type user_name_sel(uint8_t *name)
{
    uint8_t id;

    id = user_get_id_with_name(name);

    if (id >= USER_MAX)
    {
        return USER_ERR_NAME;
    }

    user.st_login = USER_LOGIN_NONE;
    user.id_now = id;
    user_copy(&user.user_list[id], &user.user_now);

    return USER_OK;
}

/****************************************************************************
 * user delete
 * **************************************************************************/
user_err_type user_add(uint32_t right, uint8_t *Name, uint8_t *password, uint8_t *tel, uint8_t *finger, uint8_t *icard)
{
    user_err_type St;
    uint8_t id;
    uint32_t Cnt;
    uint8_t *p_user;

	St = USER_OK;
	
	// 名字是否已存在
    if (user_get_id_with_name(Name) < USER_MAX)
    {
        return USER_ERR_NAME;
    }
	
	// 搜索空闲ID
    id = 0;
    for (Cnt = 1; Cnt < USER_MAX; Cnt++)
    {
        if (user.user_list[Cnt].b_enabled == 0)
        {
            id = Cnt;
            break;
        }
    }

	// 搜索成功判定
    if (0 == id)
    {
        return USER_ERR_NO_SPACE;
    }

    // clr
    p_user = (uint8_t *)&user.user_list[id];
	memset(p_user, 0, sizeof(user_type));
   
	// enable
    user.user_list[id].id_owner = user.id_now;
    user.user_list[id].b_enabled = 1;
    
    // right set
    user_right_set(id, right);
	
	// name set
	memset(user.user_list[id].name, 0, USER_NAME_LEN);
	user_str_copy(Name, user.user_list[id].name, USER_NAME_LEN);
	
	// password set
    user_password_set(id, password);

	// finger set
    if (0 != finger)
    {
		St += user_finger_set(id, finger);
    }
	
	// ic card set
	if (0 != icard)
    {
		St += user_icard_set(id, icard);
	}

	// tel set
    if (0 != tel)
    {
        user_tel_set(id, tel);
    }

    //add fail
    if (USER_OK != St)
    {
        memset(p_user, 0, sizeof(user_type));
		
        return St;
    }

    user_enable_list_get();

    return USER_OK;
}

/****************************************************************************
 * user add force
 * **************************************************************************/
user_err_type user_add_force(uint8_t id, uint32_t right, uint8_t* Name, uint8_t * password)
{
    uint8_t *p_user;

	// 名字是否已存在
	
    if (id >= USER_MAX)
    {
        return USER_ERR_NAME;
    }
	
    if (user_get_id_with_name(Name) < USER_MAX)
    {
        return USER_ERR_NAME;
    }
	
    // clr
    p_user = (uint8_t *)&user.user_list[id];
	memset(p_user, 0, sizeof(user_type));
   
	// enable
    user.user_list[id].id_owner = user.id_now;
    user.user_list[id].b_enabled = 1;
    
    // right set
    user_right_set(id, right);

    // name set
	memset(user.user_list[id].name, 0, USER_NAME_LEN);
	user_str_copy(Name, user.user_list[id].name, USER_NAME_LEN);
	
	// password set
    user_password_set(id, password);

    user_enable_list_get();

    return USER_OK;
}

/****************************************************************************
 * user delete
 * **************************************************************************/
user_err_type user_id_delete(uint8_t id)
{
    uint32_t Cnt;
    uint8_t up_level_user;
    uint8_t *p_user;
    
    if (0 == id)
    {
        return USER_ERR_RIGHT;
    }
	
	if (id == user.id_now)
    {
        return USER_ERR_ID;
    }
	
	if (id >= USER_MAX)
    {
        return USER_ERR_ID;
    }

	// slave user go up level
    up_level_user = user.user_list[id].id_owner;
	
    Cnt = USER_MAX;
	
    while (Cnt--)
    {
        if (id == user.user_list[Cnt].id_owner)
        {
            user.user_list[Cnt].id_owner = up_level_user;
        }
    }

    // clr
    p_user = (uint8_t *)&user.user_list[id];
    memset(p_user, 0, sizeof(user_type));

    user_enable_list_get();

    return USER_OK;
}

/****************************************************************************
 * user delete
 * **************************************************************************/
user_err_type user_name_delete(uint8_t *name)
{
    uint8_t id;
    
    id = user_get_id_with_name(name);
	
    if ( id > 0 && id < USER_MAX)
    {
        return user_id_delete(id);
    }
    else
    {
        return USER_ERR_NAME;
    }
}


/****************************************************************************
 * user right set
 * **************************************************************************/
user_err_type user_right_set(uint8_t id, uint32_t right)
{
    if (id >= USER_MAX)
    {
        return USER_ERR_ID;
    }

    user.user_list[id].right = right;

	// id now 
	if(id == user.id_now)
	{
		user_copy(&user.user_list[id], &user.user_now);
	}
	
    return USER_OK;
}

/****************************************************************************
 * user right add
 * **************************************************************************/
user_err_type user_right_add(uint8_t id, uint32_t right)
{
    if (id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
	
    user.user_list[id].right |= right;
	
	// id now 
	if(id == user.id_now)
	{
		user_copy(&user.user_list[id], &user.user_now);
	}
	
    return USER_OK;
}

/****************************************************************************
 * user right del
 * **************************************************************************/
user_err_type user_right_del(uint8_t id, uint32_t right)
{
    if (id >= USER_MAX)
    {
        return USER_ERR_ID;
    }

    user.user_list[id].right &= ~right;
	
	// id now 
	if(id == user.id_now)
	{
		user_copy(&user.user_list[id], &user.user_now);
	}
	
	return USER_OK;
}

/****************************************************************************
 * user right add
 * **************************************************************************/
user_err_type user_right_check(uint8_t id, uint32_t right)
{
    if (id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
    
    if((user.user_list[id].right & right) == right)
    {
        return USER_OK;
    }
    
    return USER_ERR_RIGHT;
}

/****************************************************************************
 * user and slave right add
 * **************************************************************************/
user_err_type user_and_slave_right_add(uint8_t id, uint32_t right)
{
    uint8_t index;
    
    if (id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
    
	// add right
    user.user_list[id].right |= right;
    
	// id now 
	if(id == user.id_now)
	{
		user_copy(&user.user_list[id], &user.user_now);
	}
	
	// slave user right add
    for(index=1; index < USER_MAX;index++)
    {
        if(USER_OK == user_slave_check(id , index))
        {
            user.user_list[index].right |= right;
			
			// id now 
			if(index == user.id_now)
			{
				user_copy(&user.user_list[index], &user.user_now);
			}
        }
    }
    
    return USER_OK;
}

/****************************************************************************
 * user and slave right del
 * **************************************************************************/
user_err_type user_and_slave_right_del(uint8_t id, uint32_t right)
{
    uint8_t index;
    
    if (id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
	
	// user now right delete
    user.user_list[id].right &= ~right;
    
	if(id == user.id_now)
	{
		user_copy(&user.user_list[id], &user.user_now);
	}
	
	// salve user right delete
    for(index=1; index < USER_MAX;index++)
    {
        if(USER_OK == user_slave_check(id , index))
        {
            user.user_list[index].right &= ~right;
			
			// id now 
			if(index == user.id_now)
			{
				user_copy(&user.user_list[index], &user.user_now);
			}
        }
    }
    return USER_OK;
}

/****************************************************************************
 * user password set
 * **************************************************************************/
user_err_type user_password_set(uint8_t id, uint8_t *password)
{
    if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }

    str_to_upper(password);
    
    // clear
	set_u8( user.user_list[id].password, 0, USER_PASSWORD_LEN);

    // set
	user_str_copy(password, user.user_list[id].password, USER_PASSWORD_LEN);

	// now
	if (user.id_now == id)
	{
		copy_u8(password, user.user_now.password, USER_PASSWORD_LEN);
	}	
	
    return USER_OK;
}

/****************************************************************************
 * user opt_code set
 * **************************************************************************/
user_err_type user_operator_set(uint8_t id, uint8_t *opt_code)
{
	if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }

    // clear
	set_u8(user.user_list[id].opt_code, 0, USER_OPT_CODE_LEN);

    // set
	user_str_copy(opt_code, user.user_list[id].opt_code, USER_OPT_CODE_LEN);
	
	// now
	if (user.id_now == id)
	{
		copy_u8(opt_code, user.user_now.opt_code, USER_OPT_CODE_LEN);
	}
	
    return USER_OK;
}

/****************************************************************************
 * user name set
 * **************************************************************************/
user_err_type user_name_set(uint8_t id, uint8_t *name)
{
    uint8_t nameid;

	if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
	
	// name check
    nameid = user_get_id_with_name(name);
	
	// name repet
    if ((0xFF != nameid) && (nameid != id))
    {
        return USER_ERR_RENAME;
    }
	
    // clear
    set_u8(user.user_list[id].name, 0, USER_NAME_LEN);		
	
    // set
	user_str_copy(name, user.user_list[id].name, USER_NAME_LEN);
	
	// now
	if (user.id_now == id)
	{
		copy_u8(user.user_list[id].name, user.user_now.name, USER_NAME_LEN);
	}
	
    return USER_OK;
}

/****************************************************************************
 * user finger set
 * **************************************************************************/
user_err_type user_finger_set(uint8_t id, uint8_t *finger)
{
    uint8_t fingerid;

	if(id >= USER_MAX)
	{
        return USER_ERR_ID;
    }

    //check
    fingerid = user_get_id_with_finger(finger);
    if ((0xFF != fingerid) && (fingerid != id))
    {
        return USER_ERR_REFINGER;
    }
	
    //set
	copy_u8(finger, user.user_list[id].body_info, USER_BODY_INFO_LEN);
	if (user.id_now == id)
	{
		copy_u8(finger, user.user_now.body_info, USER_BODY_INFO_LEN);
	}

    return USER_OK;
}

/****************************************************************************
 * user ic card set
 * **************************************************************************/
user_err_type user_icard_set(uint8_t id, uint8_t *icard)
{
    uint8_t icardid;

	if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
   
    //check
    icardid = user_get_id_with_icard(icard);
    if ((0xFF != icardid) && (icardid != id))
    {
        return USER_ERR_REIC_CARD;
    }

    //set
	copy_u8(icard, user.user_list[id].ic_card, USER_IC_CARD_LEN);
	if (user.id_now == id)
	{
		copy_u8(icard, user.user_now.ic_card, USER_IC_CARD_LEN);
	}

    return USER_OK;
}

/****************************************************************************
 * user password set
 * **************************************************************************/
user_err_type user_tel_set(uint8_t id, uint8_t *tel)
{
	if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
    
    //clear
	set_u8(user.user_list[id].tel, 0, USER_TEL_LEN);
	
	user_str_copy(tel, user.user_list[id].tel,USER_TEL_LEN);
	
    if (user.id_now == id)
    {
		set_u8(user.user_now.tel, 0, USER_TEL_LEN);
		user_str_copy(tel, user.user_now.tel,USER_TEL_LEN);
    }

    return USER_OK;
}

/****************************************************************************
 * creat time set
 * **************************************************************************/
user_err_type user_creat_time_set(uint8_t id, uint32_t time)
{

    /*ID rang*/
    if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
	
    user.user_list[id].creat_time = time;
	
    if(id == user.id_now)
    {
        user.user_now.creat_time = time;
    }
    
    return USER_OK;
}

/****************************************************************************
 * slave check
 * **************************************************************************/
user_err_type user_slave_check(uint8_t id_master, uint8_t id_slave)
{
    uint8_t up_level_id;

    // ID rang 
    if(id_master >= USER_MAX)
    {
        return USER_ERR_ID;
    }
    
    if(id_slave >= USER_MAX)
    {
        return USER_ERR_ID;
    }
    
	// 根用户不属于任何账户
	if(id_slave == 0)
    {
        return USER_ERR_ID;
    }
	
	// 用户开启
    if(user.user_list[id_slave].b_enabled == 0)
        return USER_ERR_ID;
	
	if(user.user_list[id_master].b_enabled == 0)
        return USER_ERR_ID;
    
    up_level_id = user.user_list[id_slave].id_owner; //上一级USER

    while (up_level_id)
    {
        if (up_level_id == id_master)
        {
            break;
        }

        if (up_level_id >= USER_MAX)
        {
            return USER_ERR_ID;
        }

        //再上一级USER
        up_level_id = user.user_list[up_level_id].id_owner;
    }

    if (up_level_id == id_master)
    {
        return USER_OK;
    }

    return USER_ERR_SLAVE;
}

/****************************************************************************
 * get id
 * **************************************************************************/
uint8_t user_get_id_with_name(uint8_t *name)
{
    uint8_t id;

    for (id = 0; id < USER_MAX; id++)
    {
        if (!user.user_list[id].b_enabled)
        {
            continue;
        }

		if (0 == comp_string(name, user.user_list[id].name, USER_NAME_LEN))
        {
			break;
        }
    }

    if (id >= USER_MAX)
    {
        id = 0xFF;
    }

    return id;
}

/****************************************************************************
 * get id
 * **************************************************************************/
uint8_t user_get_id_with_finger(uint8_t *finger)
{
    uint8_t id;

    
    for (id = 0; id < USER_MAX; id++)
    {
        if (!user.user_list[id].b_enabled)
        {
            continue;
        }

		if(0 == comp_u8(finger, user.user_list[id].body_info, USER_BODY_INFO_LEN))
		{
			break;
		}
    }

    if (id >= USER_MAX)
    {
        id = 0xFF;
    }
    
    return id;
}

/****************************************************************************
 * get id
 * **************************************************************************/
uint8_t user_get_id_with_icard(uint8_t *icard)
{
    uint8_t id;
	
    for (id = 0; id < USER_MAX; id++)
    {
        if (!user.user_list[id].b_enabled)
        {
            continue;
        }

		if(0 == comp_u8(icard, user.user_list[id].ic_card, USER_IC_CARD_LEN))
		{
			break;
		}
    }

    if (id >= USER_MAX)
    {
        id = 0xFF;
    }

    return id;
}

/****************************************************************************
 * passwork check
 * **************************************************************************/
user_err_type user_password_check(uint8_t id, uint8_t *password)
{
    user_err_type St;

    if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
    
    //no caps
    str_to_upper(password);
	
    str_to_upper(user.user_list[id].password);
    
    //user password check
    St = USER_OK;
	if(comp_string(password, user.user_list[id].password, USER_PASSWORD_LEN))
	{
		St = USER_ERR_PASSWORD;
	}
   
    if (USER_OK == St)
    {
        if((id==user.id_now) && (user.st_login == USER_LOGIN_NONE))
        {
            user.st_login = USER_LOGIN_NOR;
        }
        return USER_OK;
    }

    //supper password check
	str_to_upper(user.supper_password);
	
    St = USER_OK;
	if(comp_string(password, user.supper_password, USER_PASSWORD_LEN))
	{
		St = USER_ERR_PASSWORD;
	}
	
    if(USER_OK == St)
    {
        if((id==user.id_now) && (user.st_login == USER_LOGIN_NONE))
        {
            user.st_login = USER_LOGIN_NOR;
        }
    }
    
    return St;
}


/****************************************************************************
 * is empty
 * **************************************************************************/
uint8_t is_user_password_empty(uint8_t id)
{
    if(id > USER_MAX)
    {
        return USER_ERR_ID;
    }
	
    if( user.user_list[id].password[0] )
    {
        return 0;
    }
    
    return 1;
}

/****************************************************************************
 * operator code check
 * **************************************************************************/
user_err_type user_operator_check(uint8_t id, uint8_t *opt_code)
{
    user_err_type St;

    if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
    
    
    //user password check
    St = USER_ERR_OPERATOR;
	if(0 == comp_string(opt_code, user.user_list[id].opt_code, USER_OPT_CODE_LEN))
	{
		St =  USER_OK;
	}
   
    return St;
}

/****************************************************************************
 * finger code check
 * **************************************************************************/
user_err_type user_finger_check(uint8_t id, uint8_t *finger)
{
    uint8_t Cnt;
    user_err_type St;
    
    if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
	
	if(0 == comp_u8(finger, user.user_list[id].body_info, USER_BODY_INFO_LEN) )
		St = USER_OK;
	else
		St = USER_ERR_FINGER;
	
    if(USER_OK == St)
    {
        if((id==user.id_now) && (user.st_login == USER_LOGIN_NONE))
        {
            user.st_login = USER_LOGIN_NOR;
        }
    }
    
    return St;
}

/****************************************************************************
 * icard code check
 * **************************************************************************/
user_err_type user_icard_check(uint8_t id, uint8_t *icard)
{
    uint8_t Cnt;
    user_err_type St;
    
    if(id >= USER_MAX)
    {
        return USER_ERR_ID;
    }
    
	if(0 == comp_u8(icard, user.user_list[id].ic_card, USER_IC_CARD_LEN) )
		St = USER_OK;
	else
		St = USER_ERR_IC_CARD;
    
    if(USER_OK == St)
    {
        if((id==user.id_now) && (user.st_login == USER_LOGIN_NONE))
        {
            user.st_login = USER_LOGIN_NOR;
        }
    }
    
    return St;
}

/****************************************************************************
 * password compare
 * **************************************************************************/
user_err_type user_password_compare(uint8_t *pw1, uint8_t*pw2)
{
    user_err_type St;
    
    //no caps
    str_to_upper(pw1);
    str_to_upper(pw2);
    
    //user password check
    St = USER_OK;
	
	if( comp_string(pw1, pw2, USER_PASSWORD_LEN))
	{
		St = USER_ERR_PASSWORD;
	}

    return St;
}

/****************************************************************************
 * operator compare
 * **************************************************************************/
user_err_type user_operator_compare(uint8_t *opt1, uint8_t*opt2)
{
    user_err_type St;
    
	St = USER_OK;
	
	if( comp_string(opt1, opt2, USER_OPT_CODE_LEN))
	{
		St = USER_ERR_OPERATOR;
	}

    return St;
}

/****************************************************************************
 * finger compare
 * **************************************************************************/
user_err_type user_finger_compare(uint8_t *fg1, uint8_t*fg2)
{
    user_err_type St;
    
	if(0 == comp_u8(fg2, fg1, USER_BODY_INFO_LEN) )
		St = USER_OK;
	else
		St = USER_ERR_FINGER;
    
    return St;
}

/****************************************************************************
 * ic card compare
 * **************************************************************************/
user_err_type user_icard_compare(uint8_t *icd1, uint8_t*icd2)
{
    user_err_type St;
    
	if(0 == comp_u8(icd1, icd2, USER_IC_CARD_LEN) )
		St = USER_OK;
	else
		St = USER_ERR_IC_CARD;
    
    return St;
}

/****************************************************************************
 * user copy
 * **************************************************************************/
void user_copy(user_type *user_src, user_type *user_des)
{
    uint8_t *p_src;
    uint8_t *p_des;
    uint32_t Cnt;

    p_src = (uint8_t *)user_src;
    p_des = (uint8_t *)user_des;

    Cnt = sizeof(user_type);

    while (Cnt--)
    {
        *p_des++ = *p_src++;
    }
}

/****************************************************************************
 * user amount
 * **************************************************************************/
uint8_t user_amount(void)
{
    uint8_t id;
    uint8_t Cnt;

    Cnt = 0;
    for (id = 0; id < USER_MAX; id++)
    {
        if (user.user_list[id].b_enabled)
        {
            Cnt++;
        }
    }

    return Cnt;
}

/****************************************************************************
 * user list get
 * **************************************************************************/
uint8_t user_enable_list_get(void)
{
    uint8_t id;
    uint8_t Cnt;

	set_u8(user.enable_list, 0xFF, sizeof(user.enable_list));
    
    Cnt = 0;
    for (id = 0; id < USER_MAX; id++)
    {
        if (user.user_list[id].b_enabled)
        {
            user.enable_list[Cnt] = id;
            Cnt++;
        }
    }  
    
    return Cnt;
}

/****************************************************************************
 * user list get
 * **************************************************************************/
uint8_t user_slave_list_get(uint8_t master_id)
{
    uint8_t id;
    uint8_t Cnt;

	set_u8(user.slave_list, 0, sizeof(user.slave_list));
	
    Cnt = 0;
    for (id = 1; id < USER_MAX; id++)
    {
        if ((user.user_list[id].b_enabled) && (USER_OK == user_slave_check(master_id, id)))
        {
            user.slave_list[Cnt] = id;
            Cnt++;
        }
    }  
    
    return Cnt;
}

uint8_t user_des_slave_list_get(uint8_t master_id)
{
    uint8_t id;
    uint8_t Cnt;

	set_u8(user.slave_list, 0xFF, sizeof(user.slave_list));
	
    Cnt = 0;
    for (id = 1; id < USER_MAX; id++)
    {
        if ((user.user_list[id].b_enabled) && (user.user_list[id].id_owner == id))
        {
            user.slave_list[Cnt] = id;
            Cnt++;
        }
    }  
    
    return Cnt;
}
